package com.bq.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bq.server.base.IdEntity;
import com.bq.server.core.mapper.CadreAppointInfoMapper;
import com.bq.server.core.mapper.CadreDeptMapper;
import com.bq.server.core.mapper.DepartmentMapper;
import com.bq.server.core.model.CadreAppointInfo;
import com.bq.server.core.model.CadreDept;
import com.bq.server.core.model.Department;
import com.bq.server.core.vo.request.DepartmentRequest;
import com.bq.server.core.vo.response.DeptAndCadreInfoResponse;
import com.bq.server.enumeration.ErrorCodeEnum;
import com.bq.server.exception.BusinessException;
import com.bq.server.service.DepartmentService;
import com.bq.server.tree.TreeNode;
import com.bq.server.tree.multinode.JsonLinkedMultiTreeNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;


/**
 * 部门/组织服务实现
 *
 * @author: ChenSH
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {


    private final DepartmentMapper departmentMapper;

    private final CadreDeptMapper cadreDeptMapper;

    private final CadreAppointInfoMapper cadreAppointInfoMapper;

    @Override
    public List<TreeNode<Department>> getDepartmentTrees() {
        List<Department> list = this.list(this.lambdaQuery().getWrapper());
        return TreeNode.buildTree(list, JsonLinkedMultiTreeNode::new);
    }

    @Override
    public void remove(Long id) {
        List<Long> deptIds = getChildrenDeptId(id, departmentTreeNode -> true);
        this.removeByIds(deptIds);
    }

    @Override
    public void create(DepartmentRequest request) {
        log.info("添加部门请求参数:{}", request);
        request.checkParams();
        //查询部门下是否有重复的部门名称
        Integer deptCount = departmentMapper.selectDeptInfo(request.getDeptName(), request.getParentId());
        BusinessException.Assert.isFalse(deptCount > 0, ErrorCodeEnum.ERROR_DEPTNAME_IS_EXIST.getDescribe());
        Department department = new Department();
        BeanUtils.copyProperties(request, department);
        this.baseMapper.insert(department);
    }

    @Override
    public List<CadreAppointInfo> getCadres(Long id) {
        List<CadreDept> cadreIds = cadreDeptMapper.getCadreIdsByDeptId(id);
        if (CollUtil.isEmpty(cadreIds)) {
            return new ArrayList<>();
        }
        List<Long> collect = cadreIds.stream().map(CadreDept::getCadreId).collect(Collectors.toList());
        return cadreAppointInfoMapper.findListByIds(collect);
    }

    @Override
    public DeptAndCadreInfoResponse searchDeptAndCadres(String search) {
        DeptAndCadreInfoResponse response = new DeptAndCadreInfoResponse();
        List<CadreAppointInfo> cadreAppointInfoList = cadreAppointInfoMapper.findInfoByName(search);
        response.setCadreList(cadreAppointInfoList);
        List<Department> departments = departmentMapper.findInfoByName(search);
        response.setDeptList(departments);
        return response;
    }

    @Override
    public void updateNameById(Long id, DepartmentRequest request) {
        Department info = departmentMapper.findInfoById(id);
        BusinessException.Assert.isFalse(Objects.isNull(info), "部门信息不存在。");
        info.setDeptName(request.getDeptName());
        departmentMapper.updateById(info);
    }

    public List<Long> getChildrenDeptId(Long deptId, Predicate<TreeNode<Department>> filter) {
        List<TreeNode<Department>> departmentTrees = getDepartmentTrees();
        return departmentTrees.stream()
                .map(departmentTreeNode -> departmentTreeNode.find(node -> Objects.equals(deptId, node.data().getId())))
                .filter(Objects::nonNull)
                .filter(filter)
                .flatMap(departmentTreeNode ->
                        StreamSupport.stream(Spliterators.spliteratorUnknownSize(departmentTreeNode.iterator(), Spliterator.ORDERED), false))
                .map(TreeNode::data)
                .map(IdEntity::getId)
                .collect(Collectors.toList());
    }
}






